package com.sc.component;

import cn.hutool.core.util.ObjectUtil;
import com.sc.exception.ServiceException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author JoeZhou
 */
@Slf4j
@Aspect
@Component
public class ServiceAspect {

    @Around("execution(public * com.sc.service.impl.*.*(..))")
    @SneakyThrows
    public Object aroundAdvice(ProceedingJoinPoint pjp) {

        // 获取方法参数
        Object[] args = pjp.getArgs();
        // 组装完整业务方法名：类名.方法名()
        String className = pjp.getTarget().toString();
        className = className.substring(className.lastIndexOf('.') + 1, className.indexOf('@'));
        String methodName = pjp.getSignature().getName();
        methodName = className + "." + methodName + "()";

        // 前置通知: 检查参数中是否存在空值
        if (ObjectUtil.hasNull(args)) {
            throw new ServiceException("\n\t通知: 业务方法 " + methodName + "中存在null值参数");
        }

        // 调用目标方法
        Object returnValue = pjp.proceed(args);

        // 后置通知: 记录业务层调用日志
        log.info("\n\t方法: {}\n\t形参：{}\n\t返回：{}",
                methodName, Arrays.toString(args), returnValue);

        // 返回目标方法的返回值
        return returnValue;
    }
}
